package Common; import java.io.DataInputStream; import java.io.IOException; import java.util.HashMap; import LDraw.Support.LDrawGlobalFlag; import LDraw.Support.MatrixMath; public class Vector3f implements Cloneable { /** * @uml.property name="x" */ public float x; /** * @uml.property name="y" */ public float y; /** * @uml.property name="z" */ public float z; private int hashCode; private boolean isHashCodeValid = false; public Vector3f(float[] value) { this.x = value[0]; this.y = value[1]; this.z = value[2]; } public Vector3f(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } public Vector3f() { // TODO Auto-generated constructor stub x = 0; y = 0; z = 0; } public Vector3f(String _x, String _y, String _z) { if (_x == null || _x.length() == 0) { this.x = 0.0f; } else { this.x = Float.parseFloat(_x); } if (_y == null || _y.length() == 0) { this.y = 0.0f; } else { this.y = Float.parseFloat(_y); } if (_z == null || _z.length() == 0) { this.z = 0.0f; } else { this.z = Float.parseFloat(_z); } } public Vector3f(Vector3f v) { this.x = v.x; this.y = v.y; this.z = v.z; } public void set(float _x, float _y, float _z) { x = _x; y = _y; z = _z; isHashCodeValid = false; } /** * @return * @uml.property name="x" */ public float getX() { return x; } /** * @param x * @uml.property name="x" */ public void setX(float x) { this.x = x; isHashCodeValid = false; } /** * @return * @uml.property name="y" */ public float getY() { return y; } /** * @param y * @uml.property name="y" */ public void setY(float y) { this.y = y; isHashCodeValid = false; } /** * @return * @uml.property name="z" */ public float getZ() { return z; } /** * @param z * @uml.property name="z" */ public void setZ(float z) { this.z = z; isHashCodeValid = false; } public static Vector3f getZeroVector3f() { // TODO Auto-generated method stub return new Vector3f(0, 0, 0); } public void set(Vector3f modelX) { this.x = modelX.getX(); this.y = modelX.getY(); this.z = modelX.getZ(); isHashCodeValid = false; } public float[] getArray() { float values[] = new float[] { x, y, z }; return values; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public void Read(DataInputStream in) throws IOException { this.x = Endian.changeByteOrder(in.readFloat()); this.y = Endian.changeByteOrder(in.readFloat()); this.z = Endian.changeByteOrder(in.readFloat()); isHashCodeValid = false; } public String toString() { String string = new String(); string += String.format("%.6f, ", this.x); string += String.format("%.6f, ", this.y); string += String.format("%.6f", this.z); return string; } public Vector3f getNormal(Vector3f v0, Vector3f v2) { Vector3f normal; Vector3f v0v1 = new Vector3f(v0.x - x, v0.y - y, v0.z - z); Vector3f v2v1 = new Vector3f(v2.x - x, v2.y - y, v2.z - z); normal = new Vector3f(v0v1.y * v2v1.z - v0v1.z * v2v1.y, v0v1.z * v2v1.x - v0v1.x * v2v1.z, v0v1.x * v2v1.y - v0v1.y * v2v1.x); normal.normalize(); return normal; } public void normalize() { double length = Math.sqrt(x * x + y * y + z * z); if (length != 0.0) { this.x = (float) (this.x / length); this.y = (float) (this.y / length); this.z = (float) (this.z / length); } else { this.x = 0; this.y = 0; this.z = 0; } isHashCodeValid = false; } public final Vector3f normalizeTo(float len) { float mag = (float) Math.sqrt(x * x + y * y + z * z); if (mag > 0) { mag = len / mag; this.x *= mag; this.y *= mag; this.z *= mag; } isHashCodeValid = false; return this; } public final Vector3f getNormalizedTo(float len) { return new Vector3f(this).normalizeTo(len); } public final Vector3f getNormalized() { Vector3f ret = new Vector3f(this); ret.normalize(); return ret; } public final Vector3f cross(Vector3f v) { return new Vector3f(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y); } public final float magnitude() { return (float) Math.sqrt(x * x + y * y + z * z); } public final float dot(Vector3f v) { return x * v.x + y * v.y + z * v.z; } public final float length() { return (float) Math.sqrt(x * x + y * y + z * z); } public Vector3f sub(Vector3f other) { return new Vector3f(x - other.x, y - other.y, z - other.z); } public Vector3f sub(float _x, float _y, float _z) { return new Vector3f(x - _x, y - _y, z - _z); } public Vector3f add(Vector3f other) { return new Vector3f(x + other.x, y + other.y, z + other.z); } public Vector3f add(float _x, float _y, float _z) { return new Vector3f(x + _x, y + _y, z + _z); } public Vector3f scale(float f) { return new Vector3f(x * f, y * f, z * f); } public Vector3f div(float f) { return new Vector3f(x / f, y / f, z / f); } public static Vector3f intersectRayPlane(Vector3f start, Vector3f dir, Vector3f S1, Vector3f S2, Vector3f S3) { Vector3f dS21 = S2.sub(S1); Vector3f dS31 = S3.sub(S1); Vector3f n = dS21.cross(dS31); float ndotdR = n.dot(dir); if (Math.abs(ndotdR) < 1e-6f) // Choose your tolerance { return null; } Vector3f R1 = start.add(dir); float t = -n.dot(R1.sub(S1)) / ndotdR; Vector3f M = R1.add(dir.scale(t)); return M; } public static Vector3f intersectRayTriangle(Vector3f start, Vector3f dir, Vector3f S1, Vector3f S2, Vector3f S3) { Vector3f dS21 = S2.sub(S1); Vector3f dS31 = S3.sub(S1); Vector3f n = dS21.cross(dS31); float ndotdR = n.dot(dir); if (Math.abs(ndotdR) < 1e-6f) // Choose your tolerance { return null; } Vector3f R1 = start.add(dir); float t = -n.dot(R1.sub(S1)) / ndotdR; Vector3f M = R1.add(dir.scale(t)); Vector3f dMS1 = M.sub(S1); float u = dMS1.dot(dS21); float v = dMS1.dot(dS31); if (u >= 0.0f && u <= dS21.dot(dS21) && v >= 0.0f && v <= dS31.dot(dS31)) return null; return M; } @Override public boolean equals(Object o) { if (o == this) return true; if (Vector3f.class.isInstance(o) == false) return false; return MatrixMath.V3EqualPoints(this, (Vector3f) o); } @Override public int hashCode() { if (isHashCodeValid == false) { final String keyString = ""+Math.round(x) + "," + Math.round(y) + "," + Math .round(z); hashCode = keyString.hashCode(); isHashCodeValid = true; } return hashCode; } public void round() { this.x = Math.round(this.x / LDrawGlobalFlag.DecimalPoint) * LDrawGlobalFlag.DecimalPoint; this.y = Math.round(this.y / LDrawGlobalFlag.DecimalPoint) * LDrawGlobalFlag.DecimalPoint; this.z = Math.round(this.z / LDrawGlobalFlag.DecimalPoint) * LDrawGlobalFlag.DecimalPoint; isHashCodeValid = false; } }